#pragma once
#include<iostream>
#include<vector>
#include<unistd.h>
#include<string>
#include<cstring>
#include<sys/types.h>
#include<sys/wait.h>
#include"Task.hpp"
using namespace std;
// 可以之间写方法的实现



//先描述
class Channel
{
public:
    Channel(int fd=0,int id=0)
    :_fd(fd)
    ,_id(id)
    {
        _name="Channel"+to_string(fd)+to_string(id);
    }

    string& name()
    {
        return _name;
    }

    //发送任务码
    void Send(int code)
    {
        write(_fd,&code,sizeof(code));
    }


    void Close()
    {
        close(_fd);
    }


    void Wait()
    {
        int states=0;
        waitpid(_id,&states,0);
    }

private:
    int _fd;
    pid_t _id;
    string _name;
};

// 在组织
class ManagerChannel
{
public:
    //记录管道fd、子进程的pid
    void Inset(int fd,pid_t id)
    {
        _c.emplace_back(fd,id);
    }

    //选择管道
    Channel& Select()
    {
        Channel& c=_c[_num];
        _num++;
        _num%=_c.size();
        return c;
    }

    //关闭写端
    void CloseRead()
    {
        for(auto& e:_c)
        {
            e.Close();
            cout<<"关闭："<<e.name()<<endl;
        }
    }

    //回收子进程
    void WaitChild()
    {
        for(auto& e:_c)
        {
            e.Wait();
            cout<<"回收："<<e.name()<<endl;
        }
    }


    //关闭继承下来的全部写端
    void CloseAll()
    {
        for(auto& e:_c)
        {
            e.Close();
        }
    }

private:
    int _num=0;
    vector<Channel> _c;
};


class ProgressPoll
{
public:
    ProgressPoll(int num)
        : _num(num)
    {
    }

    //读取任务码，并执行
    void Work(int fd)
    {
        while (1)
        {
            int code;
            int n = read(fd, &code, sizeof(code));
            if (n > 0)
            {
                if(n!=sizeof(code))
                    continue;

                cout<<"子进程["<<getpid()<<"]收到一个任务码！\n";
                
                //根据任务码，执行任务
                _tm.execute(code);
            }
            else if (n == 0)
            {
                cout<<"父进程没有指定任务！子进程退出！\n";
                break;
            }
            else
            {
                cout<<"读取任务码错误！\n";
                break;
            }
        }
    }

//启动进程池
void Start()
{
    for(int i=0;i<_num;i++)
    { 
        // 创建管道
        int fd[2];
        int n = pipe(fd);
        if (n == -1)
        {
            cout << "pipe error!\n";
        }
        else
        {
            // 创建子进程
            pid_t id = fork();
            if (id == 0)
            {
                // 子进程
                //关闭继承父进程的全部写端
                _m.CloseAll();
                
                // 关闭不需要的端口
                close(fd[1]);

                // 执行任务
                Work(fd[0]);

                // 退出
                close(fd[0]);
                exit(0);     //!!!!!严重注意
            }
            else
            {
                // 父进程
                // 关闭不需要的端口
                close(fd[0]);

                //记录子进程
                _m.Inset(fd[1],id);
            }
        }
    }
}


//派送任务
void run()
{
    //选择任务
    int taskcode=_tm.code();

    //选着管道（子进程）:采取轮询选择
    auto& c=_m.Select();
    cout<<"选择子进程["<<c.name()<<"]执行任务\n";

    //发送任务码
    c.Send(taskcode);
    cout<<"发送任务码："<<taskcode<<endl;
}

//停止进程池
void Stop()
{
    //关闭写端，读端自动关闭！
    //关闭父进程写段
    _m.CloseRead();

    //等待子进程
    _m.WaitChild();
}

private:
    int _num; //需要几个子进程
    ManagerChannel _m;
    TaskManager _tm;
};